﻿//+-------------------------------------------------------------------------------------------------------------------------------------------------------
//
//Description: SqlDeploymentViewModel
//Author: Aravind Ramarathinam (aravr@microsoft.com)
//
//Copyright © Microsoft Corporation
//Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 
//You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 
//
//THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, 
//INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. 
//See the Apache Version 2.0 License for specific language governing permissions and limitations under the License.
// 
//--------------------------------------------------------------------------------------------------------------------------------------------------------


using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;
using VmroleAuthor.Models;

namespace VmroleAuthor.ViewModels
{
    public class SqlDeploymentViewModel : TreeViewItemViewModel, IDataErrorInfo, IProduceValidationResults, ICanBeRemovedFromTree
    {
        private readonly SQLDeployment  sqlDeployment;
   
        private readonly VmRoleResourceExtensionViewModel vmRoleResourceExtensionViewModel;

        private StringParameterizableProperty instanceName;
        private StringParameterizableProperty instanceID;
        private BoolParameterizableProperty enableNamedPipes;
        private BoolParameterizableProperty enableTCP;
        private StringParameterizableProperty mediaSource;
        private StringParameterizableProperty productKey;
        private EnumParameterizableProperty sqlAuthenticationType;
        private StringParameterizableProperty sqlSysAdminMemberList;       
        private IntParameterizableProperty deploymentTimeoutInSeconds;
        private StringParameterizableProperty saPassword;
        private CredentialParameterizableProperty sqlDeploymentCredential;
        private CredentialParameterizableProperty sqlAgentServiceCredential;
        private CredentialParameterizableProperty sqlServiceCredential ;
        private CredentialParameterizableProperty sqlReportingServiceCredential ;

  
        private ReferencedApplicationPayloadViewModel sqlConfigurationFile;

        public static class PropertyNames
        {
            public const string Summary = "Summary";
            public const string SqlConfigurationFile = "SqlConfigurationFile";
            public const string InstanceName = "InstanceName";
            public const string InstanceID = "InstanceID";
            public const string EnableNamedPipes = "EnableNamedPipes";
            public const string EnableTCP = "EnableTCP";
            public const string MediaSource = "MediaSource";
            public const string ProductKey = "ProductKey";
            public const string SQLAuthenticationType = "SQLAuthenticationType";
            public const string SQLSysAdminMemberList = "SQLSysAdminMemberList";
            public const string DeploymentTimeoutInSeconds = "DeploymentTimeoutInSeconds";
            public const string SAPassword = "SAPassword";          
            public const string SQLDeploymentCredential = "SQLDeploymentCredential";
            public const string SQLAgentServiceCredential = "SQLAgentServiceCredential";
            public const string SQLServiceCredential = "SQLServiceCredential";      
            public const string SQLReportingServiceCredential  = "SQLReportingServiceCredential ";  
        }

        public SqlDeploymentViewModel(
            SQLDeployment  sqlDeployment,
            TreeViewItemViewModel parentItemViewModel,
            VmRoleResourceExtensionViewModel resourceExtensionViewModel)
            : base(parentItemViewModel, true)
        {
            if (sqlDeployment == null)
            {
                sqlDeployment = new SQLDeployment();
            }
            this.sqlDeployment = sqlDeployment;          
            this.vmRoleResourceExtensionViewModel = resourceExtensionViewModel;
            this.ValidationResults = new ObservableCollection<CloudServiceModelValidationResult>();
        }

        public string Summary
        {
            get
            {                
                return "SQL Deployment";
            }
        }

        public SQLDeployment SQLDeployment
        {
            get { return this.sqlDeployment; }
        }

        public ReferencedApplicationPayloadViewModel SqlConfigurationFile
        {
            get
            {
                if (this.sqlConfigurationFile == null)
                {
                    Func<string> getter = () => this.sqlDeployment.SQLConfigurationFilePayloadId;
                    Action<string> setter = delegate(string value) { this.sqlDeployment.SQLConfigurationFilePayloadId = value; };
                    this.sqlConfigurationFile = new ReferencedApplicationPayloadViewModel(this.vmRoleResourceExtensionViewModel, ValidationHelper.PayloadType.SQLConfigurationFile, getter, setter, false, PropertyNames.SqlConfigurationFile);
                }
                return this.sqlConfigurationFile;
            }
        }

        public StringParameterizableProperty InstanceName
        {
            get
            {
                if (this.instanceName == null)
                {
                    Func<string> paramValueGetter = () => this.sqlDeployment.InstanceName;
                    Action<string> paramValueSetter = delegate(string value) { this.sqlDeployment.InstanceName = value; };
                    Func<string> autoParamNameGetter = () => PropertyNames.InstanceName;
                    ViewDefParamInfo viewDefParamInfo = new ViewDefParamInfo
                    {
                        ViewDefParameterType = ViewDefParameterType.String,
                        DefaultEnglishLabelText = "SQL deployment instance name"
                    };

                    this.instanceName = new StringParameterizableProperty(
                        PropertyNames.InstanceName,
                        paramValueGetter,
                        paramValueSetter,
                        autoParamNameGetter,
                        ParameterType.String,
                        "SQL deployment instance name",
                        this.vmRoleResourceExtensionViewModel.ResourceExtensionParametersViewModel,
                        true,
                        viewDefParamInfo);
                }
                return this.instanceName;
            }
        }

        public StringParameterizableProperty InstanceID
        {
            get
            {
                if (this.instanceID == null)
                {
                    Func<string> paramValueGetter = () => this.sqlDeployment.InstanceID;
                    Action<string> paramValueSetter = delegate(string value) { this.sqlDeployment.InstanceID = value; };
                    Func<string> autoParamNameGetter = () => PropertyNames.InstanceID;
                    ViewDefParamInfo viewDefParamInfo = new ViewDefParamInfo
                    {
                        ViewDefParameterType = ViewDefParameterType.String,
                        DefaultEnglishLabelText = "SQL deployment instance ID"
                    };

                    this.instanceID = new StringParameterizableProperty(
                        PropertyNames.InstanceID,
                        paramValueGetter,
                        paramValueSetter,
                        autoParamNameGetter,
                        ParameterType.String,
                        "SQL deployment instance ID",
                        this.vmRoleResourceExtensionViewModel.ResourceExtensionParametersViewModel,
                        true,
                        viewDefParamInfo);
                }
                return this.instanceID;
            }
        }

        /// <summary>
        /// bool
        /// </summary>   
        public BoolParameterizableProperty EnableNamedPipes
        {
            get
            {
                if (this.enableNamedPipes == null)
                {
                    Func<string> paramValueGetter = () => this.sqlDeployment.EnableNamedPipes;
                    Action<string> paramValueSetter = delegate(string value) { this.sqlDeployment.EnableNamedPipes = value; };
                    Func<string> autoParamNameGetter = () => PropertyNames.EnableNamedPipes;
                    ViewDefParamInfo viewDefParamInfo = new ViewDefParamInfo
                    {
                        ViewDefParameterType = ViewDefParameterType.Boolean,
                        DefaultEnglishLabelText = "SQL deployment Enable named pipes",
                        DefaultInitialValue = "true"
                    };

                    this.enableNamedPipes = new BoolParameterizableProperty(
                        PropertyNames.EnableNamedPipes,
                        paramValueGetter,
                        paramValueSetter,
                        autoParamNameGetter,
                        ParameterType.Boolean,
                        "SQL deployment enable named pipes",
                        this.vmRoleResourceExtensionViewModel.ResourceExtensionParametersViewModel,
                        true,
                        viewDefParamInfo
                        );
                }
                return this.enableNamedPipes;
            }
        }

        /// <summary>
        /// bool
        /// </summary>   
        public BoolParameterizableProperty EnableTCP
        {
            get
            {
                if (this.enableTCP == null)
                {
                    Func<string> paramValueGetter = () => this.sqlDeployment.EnableTCP;
                    Action<string> paramValueSetter = delegate(string value) { this.sqlDeployment.EnableTCP = value; };
                    Func<string> autoParamNameGetter = () => PropertyNames.EnableTCP;
                    ViewDefParamInfo viewDefParamInfo = new ViewDefParamInfo
                    {
                        ViewDefParameterType = ViewDefParameterType.Boolean,
                        DefaultEnglishLabelText = "SQL deployment Enable TCP",
                        DefaultInitialValue = "true"
                    };

                    this.enableTCP = new BoolParameterizableProperty(
                        PropertyNames.EnableTCP,
                        paramValueGetter,
                        paramValueSetter,
                        autoParamNameGetter,
                        ParameterType.Boolean,
                        "SQL deployment Enable TCP",
                        this.vmRoleResourceExtensionViewModel.ResourceExtensionParametersViewModel,
                        true,
                        viewDefParamInfo);
                }
                return this.enableTCP;
            }
        }

        public StringParameterizableProperty MediaSource
        {
            get
            {
                if (this.mediaSource == null)
                {
                    Func<string> paramValueGetter = () => this.sqlDeployment.MediaSource;
                    Action<string> paramValueSetter = delegate(string value) { this.sqlDeployment.MediaSource = value; };
                    Func<string> autoParamNameGetter = () => PropertyNames.MediaSource;
                    ViewDefParamInfo viewDefParamInfo = new ViewDefParamInfo
                    {
                        ViewDefParameterType = ViewDefParameterType.String,
                        DefaultEnglishLabelText = "SQL deployment media source"                        
                    };

                    this.mediaSource = new StringParameterizableProperty(
                        PropertyNames.MediaSource,
                        paramValueGetter,
                        paramValueSetter,
                        autoParamNameGetter,
                        ParameterType.String,
                        "SQL deployment media source",
                        this.vmRoleResourceExtensionViewModel.ResourceExtensionParametersViewModel,
                        true,
                        viewDefParamInfo);
                }
                return this.mediaSource;
            }
        }

        public StringParameterizableProperty ProductKey
        {
            get
            {
                if (this.productKey == null)
                {
                    Func<string> paramValueGetter = () => this.sqlDeployment.ProductKey;
                    Action<string> paramValueSetter = delegate(string value) { this.sqlDeployment.ProductKey = value; };
                    Func<string> autoParamNameGetter = () => PropertyNames.ProductKey;
                    ViewDefParamInfo viewDefParamInfo = new ViewDefParamInfo
                    {
                        ViewDefParameterType = ViewDefParameterType.String,
                        DefaultEnglishLabelText = "SQL deployment product key"
                    };

                    this.productKey = new StringParameterizableProperty(
                        PropertyNames.MediaSource,
                        paramValueGetter,
                        paramValueSetter,
                        autoParamNameGetter,
                        ParameterType.String,
                        "SQL deployment Product Key",
                        this.vmRoleResourceExtensionViewModel.ResourceExtensionParametersViewModel,
                        false,
                        viewDefParamInfo);
                }
                return this.productKey;
            }
        }

        /// <summary>
        /// SQLAuthenticationType
        /// </summary>
        public EnumParameterizableProperty SQLAuthenticationType
        {
            get
            {
                if (this.sqlAuthenticationType == null)
                {
                    Func<string> paramValueGetter = () => this.sqlDeployment.SQLAuthenticationType;
                    Action<string> paramValueSetter = delegate(string value) { this.sqlDeployment.SQLAuthenticationType = value; };
                    Func<string> autoParamNameGetter = () => PropertyNames.SQLAuthenticationType;
                    ViewDefParamInfo viewDefParamInfo = new ViewDefParamInfo
                    {
                        ViewDefParameterType = ViewDefParameterType.Option,
                        DefaultEnglishLabelText = "SQL authentication type",
                        Options = new List<string>(Enum.GetNames(typeof(SQLAuthenticationType)))
                    };

                    this.sqlAuthenticationType = new EnumParameterizableProperty(
                        PropertyNames.SQLAuthenticationType,
                        paramValueGetter,
                        paramValueSetter,
                        autoParamNameGetter,
                        ParameterType.String,
                        "SQL Authentication type",
                        this.vmRoleResourceExtensionViewModel.ResourceExtensionParametersViewModel,
                        typeof(SQLAuthenticationType),
                        false,
                        viewDefParamInfo);
                }
                return this.sqlAuthenticationType;
            }
        }


        public StringParameterizableProperty SQLSysAdminMemberList
        {
            get
            {
                if (this.sqlSysAdminMemberList == null)
                {
                    Func<string> paramValueGetter = () => this.sqlDeployment.SQLSysAdminMemberList;
                    Action<string> paramValueSetter = delegate(string value) { this.sqlDeployment.SQLSysAdminMemberList = value; };
                    Func<string> autoParamNameGetter = () => PropertyNames.SQLSysAdminMemberList;
                    ViewDefParamInfo viewDefParamInfo = new ViewDefParamInfo
                    {
                        ViewDefParameterType = ViewDefParameterType.String,
                        DefaultEnglishLabelText = "SQL sys admin member list"
                    };

                    this.sqlSysAdminMemberList = new StringParameterizableProperty(
                        PropertyNames.SQLSysAdminMemberList,
                        paramValueGetter,
                        paramValueSetter,
                        autoParamNameGetter,
                        ParameterType.String,
                        "SQL sys admin member list ",
                        this.vmRoleResourceExtensionViewModel.ResourceExtensionParametersViewModel,
                        true,
                        viewDefParamInfo);
                }
                return this.sqlSysAdminMemberList;
            }
        }

        public IntParameterizableProperty DeploymentTimeoutInSeconds
        {
            get
            {
                if (this.deploymentTimeoutInSeconds == null)
                {
                    Func<string> paramValueGetter = () => this.sqlDeployment.DeploymentTimeoutInSeconds;
                    Action<string> paramValueSetter = delegate(string value) { this.sqlDeployment.DeploymentTimeoutInSeconds = value; };
                    Func<string> autoParamNameGetter = () => PropertyNames.DeploymentTimeoutInSeconds;
                    ViewDefParamInfo viewDefParamInfo = new ViewDefParamInfo
                    {
                        ViewDefParameterType = ViewDefParameterType.Number,
                        DefaultEnglishLabelText = "SQL deployment timeout in seconds",
                        DefaultInitialValue = int.MaxValue.ToString(CultureInfo.InvariantCulture)
                    };

                    this.deploymentTimeoutInSeconds = new IntParameterizableProperty(
                        PropertyNames.DeploymentTimeoutInSeconds,
                        paramValueGetter,
                        paramValueSetter,
                        autoParamNameGetter,
                        ParameterType.Int,
                        "SQL deployment timeout in seconds",
                        this.vmRoleResourceExtensionViewModel.ResourceExtensionParametersViewModel,
                        true,
                        viewDefParamInfo);
                }
                return this.deploymentTimeoutInSeconds;
            }
        }

        public StringParameterizableProperty SAPassword
        {
            get
            {
                if (this.saPassword == null)
                {
                    Func<string> paramValueGetter = () => this.sqlDeployment.SAPassword;
                    Action<string> paramValueSetter = delegate(string value) { this.sqlDeployment.SAPassword = value; };
                    Func<string> autoParamNameGetter = () => PropertyNames.SAPassword;
                    ViewDefParamInfo viewDefParamInfo = new ViewDefParamInfo
                    {
                        ViewDefParameterType = ViewDefParameterType.SecureString,
                        DefaultEnglishLabelText = "SQL SA password"
                    };

                    this.saPassword = new StringParameterizableProperty(
                        PropertyNames.SAPassword,
                        paramValueGetter,
                        paramValueSetter,
                        autoParamNameGetter,
                        ParameterType.String,
                        "SQL deployment SA password",
                        this.vmRoleResourceExtensionViewModel.ResourceExtensionParametersViewModel,
                        false,
                        viewDefParamInfo);
                }
                return this.saPassword;
            }
        }             

        public CredentialParameterizableProperty SQLDeploymentCredential
        {
            get
            {
                if (this.sqlDeploymentCredential == null)
                {
                    Func<string> paramValueGetter = () => this.sqlDeployment.SQLDeploymentCredential;
                    Action<string> paramValueSetter = delegate(string value) { this.sqlDeployment.SQLDeploymentCredential = value; };
                    Func<string> autoParamNameGetter = () => PropertyNames.SQLDeploymentCredential;
                    ViewDefParamInfo viewDefParamInfo = new ViewDefParamInfo
                    {
                        ViewDefParameterType = ViewDefParameterType.Credential,
                        DefaultEnglishLabelText = "SQL deployment credential"
                    };

                    this.sqlDeploymentCredential = new CredentialParameterizableProperty(
                        PropertyNames.SQLDeploymentCredential,
                        paramValueGetter,
                        paramValueSetter,
                        autoParamNameGetter,
                        ParameterType.Credential,
                        "SQL deployment credential",
                        this.vmRoleResourceExtensionViewModel.ResourceExtensionParametersViewModel,
                        false,
                        viewDefParamInfo);
                }
                return this.sqlDeploymentCredential;
            }
        }

        public CredentialParameterizableProperty SQLAgentServiceCredential
        {
            get
            {
                if (this.sqlAgentServiceCredential == null)
                {
                    Func<string> paramValueGetter = () => this.sqlDeployment.SQLAgentServiceCredential;
                    Action<string> paramValueSetter = delegate(string value) { this.sqlDeployment.SQLAgentServiceCredential = value; };
                    Func<string> autoParamNameGetter = () => PropertyNames.SQLAgentServiceCredential;
                    ViewDefParamInfo viewDefParamInfo = new ViewDefParamInfo
                    {
                        ViewDefParameterType = ViewDefParameterType.Credential,
                        DefaultEnglishLabelText = "SQL agent service credential"
                    };

                    this.sqlAgentServiceCredential = new CredentialParameterizableProperty(
                        PropertyNames.SQLAgentServiceCredential,
                        paramValueGetter,
                        paramValueSetter,
                        autoParamNameGetter,
                        ParameterType.Credential,
                        "SQL deployment SQL agent service credential",
                        this.vmRoleResourceExtensionViewModel.ResourceExtensionParametersViewModel,
                        false,
                        viewDefParamInfo);
                }
                return this.sqlAgentServiceCredential;
            }
        }

        public CredentialParameterizableProperty SQLServiceCredential
        {
            get
            {
                if (this.sqlServiceCredential == null)
                {
                    Func<string> paramValueGetter = () => this.sqlDeployment.SQLServiceCredential;
                    Action<string> paramValueSetter = delegate(string value) { this.sqlDeployment.SQLServiceCredential = value; };
                    Func<string> autoParamNameGetter = () => PropertyNames.SQLServiceCredential;
                    ViewDefParamInfo viewDefParamInfo = new ViewDefParamInfo
                    {
                        ViewDefParameterType = ViewDefParameterType.Credential,
                        DefaultEnglishLabelText = "SQL deployment service credential"
                    };

                    this.sqlServiceCredential = new CredentialParameterizableProperty(
                        PropertyNames.SQLServiceCredential,
                        paramValueGetter,
                        paramValueSetter,
                        autoParamNameGetter,
                        ParameterType.Credential,
                        "SQL deployment SQL service credential",
                        this.vmRoleResourceExtensionViewModel.ResourceExtensionParametersViewModel,
                        false,
                        viewDefParamInfo);
                }
                return this.sqlServiceCredential;
            }
        }

        public CredentialParameterizableProperty SQLReportingServiceCredential
        {
            get
            {
                if (this.sqlReportingServiceCredential == null)
                {
                    Func<string> paramValueGetter = () => this.sqlDeployment.SQLReportingServiceCredential;
                    Action<string> paramValueSetter = delegate(string value) { this.sqlDeployment.SQLReportingServiceCredential = value; };
                    Func<string> autoParamNameGetter = () => PropertyNames.SQLReportingServiceCredential;
                    ViewDefParamInfo viewDefParamInfo = new ViewDefParamInfo
                    {
                        ViewDefParameterType = ViewDefParameterType.Credential,
                        DefaultEnglishLabelText = "SQL deployment reporting service credential"
                        //TODO: default
                    };

                    this.sqlReportingServiceCredential = new CredentialParameterizableProperty(
                        PropertyNames.SQLReportingServiceCredential,
                        paramValueGetter,
                        paramValueSetter,
                        autoParamNameGetter,
                        ParameterType.Credential,
                        "SQL deployment reporting service credential",
                        this.vmRoleResourceExtensionViewModel.ResourceExtensionParametersViewModel,
                        false,
                        viewDefParamInfo);  
                }
                return this.sqlReportingServiceCredential;
            }
        }

        protected override void LoadChildren()
        {
            // No children                          
        }

        public void Cleanup()
        {
            this.IsExpanded = true;
            ParametersAndPayloadCleanupHelper.CleanupParametersAndPayload(this, typeof(PropertyNames));
        }

        public ObservableCollection<CloudServiceModelValidationResult> ValidationResults { get; private set; }

        public void UpdateValidationResults()
        {
            this.IsExpanded = true;
            ModelValidationResultsHelper.UpdateValidationResults(this, typeof(PropertyNames));
            //Add any other cross-field validations error           
        }

        public string this[string columnName]
        {
            get { return null; }
        }

        public string Error { get; set; }
    }
}
